//-----------------------------------------------------------------------------
//  Copyright (C) 2011-2018, GB Research, LLC (www.gbresearch.com)
//  
//  Boost Software License - Version 1.0 - August 17th, 2003
//
//  Permission is hereby granted, free of charge, to any person or organization
//  obtaining a copy of the software and accompanying documentation covered by
//  this license (the "Software") to use, reproduce, display, distribute,
//  execute, and transmit the Software, and to prepare derivative works of the
//  Software, and to permit third-parties to whom the Software is furnished to
//  do so, all subject to the following:
//
//  The copyright notices in the Software and this entire statement, including
//  the above license grant, this restriction and the following disclaimer,
//  must be included in all copies of the Software, in whole or in part, and
//  all derivative works of the Software, unless such copies or derivative
//  works are solely in the form of machine-executable object code generated by
//  a source language processor.
//
//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//  FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
//  SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
//  FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
//  ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
//  DEALINGS IN THE SOFTWARE.
//-----------------------------------------------------------------------------

#pragma once

#include "axe_terminal_function.h"
#include "axe_composite_function.h"
#include "axe_predicate_function.h"
#include "axe_numeric_function.h"

namespace axe
{
    namespace shortcuts
    {
        const auto _ = axe::r_any(); // any char
        const auto _a = axe::r_alpha(); // single letter or _
        const auto _d = axe::r_num(); // single decimal digit
        const auto _double = axe::r_double(); // double representation
        const auto _hs = axe::r_any(" \t"); // horisontal space
        const auto _ident = r_ident(); // identifier, a letter (including underscore) followed by letters and digits
        const auto _int = axe::r_decimal(); // integer representation
        const auto _n = axe::r_char('\n'); // eol
        const auto _o = axe::r_oct(); // octal char
        const auto _r = axe::r_char('\r'); // CR
        const auto _s = axe::r_char(' '); // space
        const auto _t = axe::r_char('\t'); // tab char
        const auto _uint = axe::r_udecimal(); // unsinged integer representation
        const auto _ws = axe::r_pred(axe::is_wspace()); // white-space separators (" \t\n\r")
        const auto _w = axe::r_alnumstr(); // alnum word
        const auto _x = axe::r_hex(); // hex char
        const auto _z = axe::r_end(); // end of range
        const auto _endl = *_hs & (_n | _z); // horizontal spaces and eol or eor

    #if defined(__GNUC__)
        // non-standard, GCC specific, will be changed in C++20
        // http://open-std.org/JTC1/SC22/WG21/docs/papers/2013/n3599.html
        // www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0424r2.pdf
        template <class T, T... C> constexpr auto operator "" _axe() { return axe::r_strlit<C...>{}; }
    #else
        //---------------------------------------
        inline auto operator "" _axe(const char* str, size_t)
        {
            return axe::r_str(str);
        }

        //---------------------------------------
        inline auto operator "" _axe(const wchar_t* str, size_t)
        {
            return axe::r_str(str);
        }
    #endif
        //---------------------------------------
        inline auto operator "" _axe(char c)
        {
            return axe::r_char(c);
        }

        //---------------------------------------
        inline auto operator "" _axe(wchar_t c)
        {
            return axe::r_char(c);
        }

        //---------------------------------------
        inline auto operator "" _any(const char* str, size_t)
        {
            return axe::r_any(str);
        }

        //---------------------------------------
        inline auto operator "" _any(const wchar_t* str, size_t)
        {
            return axe::r_any(str);
        }

        //---------------------------------------
        inline auto operator "" _regex(const char* str, size_t)
        {
            return axe::r_regex(str);
        }

        //---------------------------------------
        inline auto operator "" _regex(const wchar_t* str, size_t)
        {
            return axe::r_regex(str);
        }
    }
}
